package cn.tedu.rewrite;

import org.junit.Test;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author :Colin
 * @version 创建时间: 2021/6/25 11:46
 *本类用于测试暴力反射
 */
public class TestReflect2 {
    /*1.暴力反射获取于设置私有属性值*/
    @Test
    public void getFields() throws Exception {
        Class<Person> clazz = Person.class;
        Field field = clazz.getDeclaredField("name");
        //根据获取的属性对象拿到类型
        System.out.println(field.getType().getName());
        System.out.println(field.getType());
        //设置属性的值
        Person p = clazz.newInstance();
        Object obj = clazz.newInstance();
        //暴力反射，注意，设置私有可见，不然访问不了
        field.setAccessible(true);
        field.set(obj,"林场");
        System.out.println(field.get(obj));
        
        field.set(p,"林场p");
        System.out.println(field.get(p));
    }
    @Test
    /*单元测试2：通过暴力反射获取方法*/
    public void getFunction() throws Exception {
        //1.获取目标资源对应的字节码对象
        Class<?> clazz = Person.class;
        //2.通过暴力反射获取私有方法
        /*本方法的参数列表是getDeclaredMethod(name,x,y,z...)
         * name:指的是要获取方法的名字
         * x,y,z...可变参数，指的是要获取方法的参数类型，注意是字节码对象“.class”*/
        Method method = clazz.getDeclaredMethod("add", String.class, int.class);
        //3.1没有对象就通过反射创建对象
        Object obj = clazz.newInstance();

        //3.2如果想要执行私有的方法，也要设置私有可见
        method.setAccessible(true);
        //3.3执行获取到的这个私有方法
        /*invoke()用来调用目标方法，参数1是执行哪个对象的这个方法
        后续的参数是执行目标方法时传入的参数，这个参数是可变参数，根据目标方法的具体情况来写*/
        method.invoke(obj,"李四儿",18);
    }
}
